#include<cstdio>//uncle-lu
#include<cmath>
#include<queue>
#include<cstring>
#include<algorithm>
template<class T>void read(T &x)
{
	x=0;int f=0;char ch=getchar();
	while(ch<'0'||ch>'9') { f|=(ch=='-'); ch=getchar(); }
	while(ch<='9'&&ch>='0') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
	x = f ? -x : x;
	return ;
}

void init(void);
void add_edge(int, int, int, int);
long long int dijskra(void);

struct Heap_node{
	int number;
	long long int val;
	friend bool operator<(const Heap_node a, const Heap_node b){
		return a.val>b.val;
	}
	Heap_node(int num,long long int v) { number = num; val = v; }
};
struct node{
	int v,from,c,t;
	int next;
};

node edge[200010];
int head[100010],cnt;
long long int d[200010];
bool visit[200010];
int n,m;

void init()
{
	memset(head,-1,sizeof(head));
	memset(visit,false,sizeof(visit));
	cnt=0;
	return ;
}

void add_edge(int x, int y, int c, int t)
{
	cnt++;
	edge[cnt].v = y;
	edge[cnt].from = x;
	edge[cnt].c = c;
	edge[cnt].t = t;
	edge[cnt].next = head[x];
	head[x] = cnt;
	return ;
}

long long int dijskra()
{
	std::priority_queue<Heap_node>qu;

	memset(d,0x7f7f7f7f,sizeof(d));
	for(int i=head[1];~i;i=edge[i].next)
	{
		d[i] = edge[i].t;
		qu.push(Heap_node(i,d[i]));
	}

	while(!qu.empty())
	{
		Heap_node now = qu.top();
		qu.pop();

		visit[now.number] = true;

		int v = edge[now.number].v;
		if(v == n)return d[now.number];

		for(int i=head[v];~i;i=edge[i].next)
		{
			if(visit[i])continue;
			if(d[i] > d[now.number] + (long long int)edge[i].t + (long long int)abs(edge[i].c - edge[now.number].c) )
			{
				d[i] = d[now.number] + (long long int)edge[i].t + (long long int)abs(edge[i].c - edge[now.number].c);
				qu.push(Heap_node(i,d[i]));
			}
		}
	}

	return 0;
}

int main()
{
	int a,b,c,t;
	while(~scanf("%d%d",&n,&m))
	{
		init();
		for(int i=1;i<=m;++i)
		{
			read(a);read(b);read(c);read(t);
			add_edge(a,b,c,t);
			add_edge(b,a,c,t);
		}
		printf("%lld\n",dijskra());
	}
	return 0;
}
